#pragma once

#include "IThreadPoolWorkerJob.h"
#include "Common.h"
#include "MD5Signature.h"
#include "InfectedHandler.h"
#include "Semaphore.h"
#include "Event.h"
#include "CriticalSection.h"
#include <string>
#include <vector>
#include <CL\cl.hpp>

namespace GPUCC
{
	// todo: fix this!!!
	class KernelHandler;

	class BaseScanGroup
	{
	public:
		class CompareJob : public CPU::IThreadPoolWorkerJob
		{
		public:
			CompareJob(BaseScanGroup* Group, const std::vector<MD5Signature>& Signatures, InfectedHandler& Handler);
			virtual ~CompareJob();

			virtual void Run();

		private:
			BaseScanGroup* m_Group;
			const std::vector<MD5Signature>& m_Signatures;
			InfectedHandler& m_Handler;
		};

		BaseScanGroup(unsigned int Size, unsigned int MaxItemSize, KernelHandler& Handler, cl::Program* prog, cl::Context* context, cl::CommandQueue* queue);
		virtual ~BaseScanGroup();

		virtual bool IsFull();
		unsigned int GetGroupSize();
		unsigned int GetItemsCount();

		bool AddItem(const std::string& FilePath, unsigned int Size);
		virtual void Scan() = 0;

		virtual void Clear();

	protected:
		virtual void AddItemInfo(unsigned int Size) = 0;

		virtual void SetScanFinished();

		unsigned int m_Size;
		std::vector<std::string> m_Names;
		std::vector<BUFFER_INFO> m_Info;
		std::vector<MD5Signature::MD5Array> m_Hashes;
		unsigned int m_CurrentOffset;
		std::vector<unsigned char> m_Data;

		cl::Program* m_Program;
		cl::Context* m_Context;
		cl::CommandQueue* m_Queue;

		cl::Kernel m_LocalKernel;

		cl::Buffer m_DeviceInfo;
		cl::Buffer m_DeviceData;
		cl::Buffer m_DeviceHash;

		CPU::Event m_Finished;

		KernelHandler& m_Handler;
	};
}